﻿using DXBase.D3D;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace DXBase.Structs
{
	/// <summary>
	/// Structure returned by the MeshLoader (non WinRT, defined in DXBase.Samples.MeshLoader) 
	/// </summary>
	[StructLayout(LayoutKind.Sequential)]
	public struct BasicVertex
	{
		public Vector3F Pos;   // position
		public Vector3F Norm;  // surface normal vector
		public Vector2F Tex;   // texture coordinate
		public Color4B Color;

		public static VertexLayout GetLayout()
		{
			var result = new VertexLayout();
			result.Add("POSITION", Format.R32G32B32_float, 0);
			result.Add("NORMAL", Format.R32G32B32_float, 0);
			result.Add("TEXCOORD", Format.R32g32_float, 0);
			result.Add("COLOR", Format.B8g8r8a8_unorm, 0);
			return result;
		}
	}

	[StructLayout(LayoutKind.Sequential)]
	public struct DirectionalLight
	{
		public Vector4F ambient;
		public Vector4F diffuse;
		public Vector4F specular;
		public Vector3F direction;
		public float PADDING; // pad the last to Vector4F so can be used in an array
	}
	[StructLayout(LayoutKind.Sequential)]
	public struct SpotLight
	{
		public Vector4F ambient;
		public Vector4F diffuse;
		public Vector4F specular;
		// packed in Vector4F: pos and range
		public Vector3F position;
		public float range;
		public Vector3F direction;
		public float spot;
		public Vector3F attenuation;
		public float pad;
	}
	[StructLayout(LayoutKind.Sequential)]
	public struct PointLight
	{
		public Vector4F ambient;
		public Vector4F diffuse;
		public Vector4F specular;
		// packed in Vector4F: pos and range
		public Vector3F position;
		public float range;
		// a0 + a1 * x + a2 * x^2
		public Vector3F attenuation;
		public float PADDING; // pad the last to Vector4F so can be used in an array
	}
	[StructLayout(LayoutKind.Sequential)]
	public struct Material
	{
		public Vector4F ambient;
		public Vector4F diffuse;
		public Vector4F specular; // w = SpecPower
		public Vector4F reflect;
	}

	[Flags]
	public enum DrawFlag : uint
	{
		/// <summary>
		/// Draw the current item with a texture
		/// </summary>
		UseTexel  = 1,
		/// <summary>
		/// Draw the current item using the vertex's color
		/// </summary>
		UseVertexColor = 2,
		/// <summary>
		/// Draw the item with the co
		/// </summary>
		UseFixColor = 4,
		/// <summary>
		/// Clip the pixel according to their alpha
		/// </summary>
		AlphaClip = 8,
	}

	/// <summary>
	/// describes the constant buffer that will be used to draw
	/// it is used by BasicVertexShader and BasicPixelShader and is expected at slot 4
	/// </summary>
	[StructLayout(LayoutKind.Sequential)]
	public struct PerObjectData
	{
		public Matrix4x4F WorldModel;
		public Matrix4x4F WorldModelNorm; // matrix to transform normals
		public Matrix4x4F projection;
		public Material material;

		// experiments
		public Vector3F fixcolor;
		public Windows.UI.Color FixColor
		{
			get { return Windows.UI.Color.FromArgb(255, fixcolor.X.Colorb(), fixcolor.Y.Colorb(), fixcolor.Z.Colorb()); }
			set { fixcolor = new Vector3F(value.R.Colorf(), value.G.Colorf(), value.B.Colorf()); }
		}
		public DrawFlag DrawFlags;
	}

	/// <summary>
	/// describes the constant buffer that will be used to draw
	/// it is used by BasicVertexShader and BasicPixelShader and is expected at slot 0
	/// </summary>
	[StructLayout(LayoutKind.Sequential)]
	public struct PerFrameData
	{
		public Vector3F gEyePosW;
		float PAD0;
		/// <summary>
		/// Maximum 256 <see cref="DirectionalLight"/> lights should in slot 2, for BasicPixelShader
		/// </summary>
		public int nDirLights;
		/// <summary>
		/// Maximum 204 <see cref="PointLight"/> lights should in slot 3, for BasicPixelShader
		/// </summary>
		public int nPointLights;
		/// <summary>
		/// Maximum 170 <see cref="SpotLight"/> lights should in slot 3, for BasicPixelShader
		/// </summary>
		public int nSpotLight;
		int pad2;
	}
}
